import json
import os
import shutil
import time
import zipfile
from functools import wraps
from io import BytesIO

import flask
from flask import session, make_response, url_for

from applications.common.utils.gen_captcha import vieCode


def chklogin(func):
    @wraps(func)
    def check_login(*args, **kwargs):
        if '__islogin' not in session:
            session['__islogin'] = False
        if session['__islogin'] != True:
            return flask.redirect(url_for('users.users_index.login'))
        return func(*args, **kwargs)
    return check_login

def init_login(uinfo):
    session['__islogin'] = True

def init_captcha():
    image, code = vieCode().GetCodeImage()
    code = ''.join(code).lower()
    out = BytesIO()
    session["code"] = code
    image.save(out, 'png')
    out.seek(0)
    resp = make_response(out.read())
    resp.content_type = 'image/png'
    return resp, code

def dir_and_file_tree(path, temp_list):
    path_tree = os.listdir(path)  # 获取当前目录下的文件和目录
    for item in path_tree:
        subtree = path + '/' + item
        if os.path.isdir(subtree):  # 判断是否为目录
            x1 = []
            item_dict = {'path':subtree, 'title': item, 'type': 'dir', 'children': x1}
            temp_list.append(item_dict)
            dir_and_file_tree(subtree, x1)  # 递归深度优先遍历
        else:
            temp_list.append({'path':subtree, 'title': item, 'type': 'file'})
    return temp_list

def tconf(app, key, val=None, des=None):
    if app == 'sys':
        jsonfile = 'etc/conf/config.json'
    else:
        jsonfile = 'plugins/%s/config/config.json' % app
    if val is not None:
        # 写入
        if os.path.exists(jsonfile):
            with open(jsonfile, 'r', encoding='utf-8') as f:
                config = json.loads(f.read())
            if key in config.keys():
                config[key]['val'] = val
                config[key]['des'] = des
            else:
                config[key] = {'key':key,'val': val, 'des': des}
            with open(jsonfile, 'w', encoding='utf-8') as f:
                f.write(json.dumps(config, ensure_ascii=False, indent=4))
        else:
            dirname = os.path.dirname(jsonfile)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            config = {key: {'key':key,'val': val, 'des': des}}
            with open(jsonfile, 'w', encoding='utf-8') as f:
                f.write(json.dumps(config, ensure_ascii=False, indent=4))
    else:
        # 读取
        if os.path.exists(jsonfile):
            with open(jsonfile, 'r', encoding='utf-8') as f:
                config = json.loads(f.read())
            if key in config.keys():
                return config[key]['val']
            else:
                return ''
        else:
            return None

def rmconf(app, key):
    if app == 'sys':
        jsonfile = 'etc/conf/config.json'
    else:
        jsonfile = 'plugins/%s/config/config.json' % app
    if os.path.exists(jsonfile):
        with open(jsonfile, 'r', encoding='utf-8') as f:
            config = json.loads(f.read())
        if key in config.keys():
            del config[key]
            with open(jsonfile, 'w', encoding='utf-8') as f:
                f.write(json.dumps(config, ensure_ascii=False, indent=4))
            return True
        else:
            return False
    else:
        return False

def generate_tree(source, parent, cache=[], id="id" ,pid="pid", child="child"):
    tree = []
    for item in source:
        if item[id] in cache:
            continue
        if item[pid] == parent:
            cache.append(item[id])
            item[child] = generate_tree(source, item[id], cache=cache, id=id ,pid=pid, child=child)
            tree.append(item)
    return tree


def generate_tree_with_parent(source, parent, cache=[], id="id" ,pid="pid", child="child"):
    tree = []
    for item in source:
        if item[id] in cache:
            continue
        if item[pid] == parent or item[id] == parent:
            cache.append(item[id])
            item[child] = generate_tree_with_parent(source, item[id], cache=cache, id=id ,pid=pid, child=child)
            tree.append(item)
    return tree

# 只打包文件，空文件夹都不打包
def zip_folder(folder_path, zip_path):
    # 创建一个空 zip 文件
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        # 遍历文件夹及其子文件夹
        for root, dirs, files in os.walk(folder_path):
            for file in files:
                # 获取文件的相对路径
                file_path = os.path.join(root, file).replace(folder_path, '')
                # 将文件添加到 zip 文件中
                zipf.write(os.path.join(root, file), os.path.join(zip_path, file_path))

# 打包整个文件夹到zip，包括空文件夹
def zipfolder(folder_path, zip_path):
    # 创建一个空 zip 文件
    zippath = os.path.basename(folder_path)
    if not zippath:
        zippath = os.path.basename(os.path.dirname(folder_path))
    else:
        zippath = ''
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        # 遍历文件夹及其子文件夹
        _zip_folder(zipf, folder_path, zippath)
def _zip_folder(zf, path, zippath):
    if os.path.isfile(path):
        zf.write(path, zippath, zipfile.ZIP_DEFLATED)
    elif os.path.isdir(path):
        if zippath:
            zf.write(path, zippath)
        for nm in sorted(os.listdir(path)):
            _zip_folder(zf,
                     os.path.join(path, nm), os.path.join(zippath, nm))

def cache_file(file, cachedata=None, cache_time=3600):
    cache_path = 'data/_cache'
    if not os.path.exists(cache_path):
        os.makedirs(cache_path)
    cache_file = os.path.join(cache_path, file)
    if cachedata is not None:
        with open(cache_file, 'w', encoding='utf-8') as f:
            f.write(json.dumps(cachedata))
    else:
        if not os.path.exists(cache_file):
            return None
        mtime = os.path.getmtime(cache_file)
        if time.time() - mtime > cache_time:
            return None
        else:
            with open(cache_file, 'r', encoding='utf-8') as f:
                return json.loads(f.read())